using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlTypes;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
using System.Xml;

namespace ADC
{
    public partial class Form : System.Windows.Forms.Form
    {
        public Form()
        {
            InitializeComponent();

            Clear();

            LoadSet();
            ListConnect();

            groupBox3.Text = "Frame " + Convert.ToString(arrTrackFrame[TrackFrame.Value]);
        }

        string CONFIG_NAME = "set.config";

        string selectPort, Ports;
        string trackFrame;

        #region Configuration

        public void LoadMainConfFromXml()
        {
            string configFile = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), CONFIG_NAME);

            if (File.Exists(configFile))
            {
                FileStream fs = new FileStream(configFile, FileMode.Open);
                try
                {
                    LoadMainConfFromXml(fs);
                }
                finally
                {
                    fs.Close();
                }
            }
            else
            {
                MessageBox.Show("set.config не найден!");
                Application.Exit();
            }
        }

        public void LoadMainConfFromXml(Stream stream)
        {
            XmlTextReader xmlIn = new XmlTextReader(stream);
            xmlIn.WhitespaceHandling = WhitespaceHandling.None;
            xmlIn.MoveToContent();

            MoveToNextElement(xmlIn);
            if (xmlIn.Name == "Device")
            {
                selectPort = xmlIn.GetAttribute("selectPort");
                Ports = xmlIn.GetAttribute("Ports");
            }
            MoveToNextElement(xmlIn);
            if (xmlIn.Name == "Frame")
            {
                trackFrame = xmlIn.GetAttribute("trackFrame");
            }
            xmlIn.Close();
        }

        public static void MoveToNextElement(XmlTextReader xmlIn)
        {
            xmlIn.Read();
            if (xmlIn.NodeType == XmlNodeType.EndElement)
                xmlIn.Read();
        }

        public int SaveMainConfAsXml(string filename, Encoding encoding)
        {
            int err = 0;
            string tempFile = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "temp.config");
            FileStream fs = new FileStream(tempFile, FileMode.Create);
            try
            {
                SaveMainConfAsXml(fs, encoding);
                fs.Close();
                File.Copy(tempFile, filename, true);
                File.Delete(tempFile);
            }
            catch
            {
                err = 1;
            }
            return err;
        }

        public void SaveMainConfAsXml(Stream stream, Encoding encoding)
        {
            XmlTextWriter xmlOut = new XmlTextWriter(stream, encoding);
            xmlOut.Formatting = Formatting.Indented;
            xmlOut.WriteStartDocument();
            xmlOut.WriteStartElement("Set");
            xmlOut.WriteStartElement("Device");
            xmlOut.WriteAttributeString("selectPort", selectPort);
            xmlOut.WriteAttributeString("Ports", Ports);
            xmlOut.WriteEndElement();
            xmlOut.WriteStartElement("Frame");
            xmlOut.WriteAttributeString("trackFrame", trackFrame);
            xmlOut.WriteEndElement();
            xmlOut.WriteEndElement();
            xmlOut.Close();
        }

        #endregion

        //

        private void LoadSet()
        {
            LoadMainConfFromXml(); // Загрузка параметров из xml файла

            ConnectDevice.Text = selectPort;

            TrackFrame.Value = Convert.ToInt32(trackFrame);
        }

        private void SaveSet()
        {
            selectPort = ConnectDevice.Text;

            trackFrame = Convert.ToString(TrackFrame.Value);
        }

        private void ListConnect()
        {
            string[] arrPorts = Ports.Split(new char[] { ';' });

            ConnectDevice.Items.Clear();

            foreach (string s in arrPorts)
            {
                ConnectDevice.Items.Add(s);
            }
        }

        bool bButtonConnect;
        private void ButtonConnect_Click(object sender, EventArgs e)
        {
            try
            {
                if (bButtonConnect == false)
                {
                    bButtonConnect = true;
                    ButtonConnect.Text = "Disconnect";
                    serialPort.PortName = ConnectDevice.Text;
                    serialPort.Open();
                    Clear();
                }
                else
                {
                    bButtonConnect = false;
                    ButtonConnect.Text = "Connect";
                    serialPort.Close();
                    sReceivedAnalog = "0.0";
                    bReceived = false;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                bButtonConnect = false;
                ButtonConnect.Text = "Connect";
            }
        }

        private void Clear()
        {
            sSecond2 = "";
            sHour2 = "";

            inAnalog = 0;

            for (int i = 0; i < 600; i++)
            {
                arrAnalog[0, i] = "0";
                arrAnalog[1, i] = "0";
            }
        }

        string sReceivedAnalog = "0.0";
        bool bReceived;
        bool bSignal;
        private void serialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            sReceivedAnalog = serialPort.ReadLine();
            bReceived = true;
            bSignal = true;
        }

        string sDateTime;
        string sSecond2;
        string sHour2;

        double dAnalog;
        int iAnalog;
        string sAnalog;

        int iTrackFrame;
        int[] arrTrackFrame = new int[6] { 10, 20, 60, 100, 200, 600 };

        int inAnalog;
        string[,] arrAnalog = new string[2, 600];
        private void Timer_Tick(object sender, EventArgs e)
        {
            DateTime moment = DateTime.Now;

            int iYear = moment.Year;
            int iMonth = moment.Month;
            int iDay = moment.Day;
            int iHour = moment.Hour;
            int iMinute = moment.Minute;
            int iSecond = moment.Second;

            string sYear = string.Format("{0:d4}", iYear);
            string sMonth = string.Format("{0:d2}", iMonth);
            string sDay = string.Format("{0:d2}", iDay);
            string sHour = string.Format("{0:d2}", iHour);
            string sMinute = string.Format("{0:d2}", iMinute);
            string sSecond = string.Format("{0:d2}", iSecond);

            if (sSecond != sSecond2 && bButtonConnect == true && bReceived == true)
            {
                sSecond2 = sSecond;

                sDateTime = Convert.ToString(DateTime.Now);

                if (bSignal == true)
                {
                    bSignal = false;

                    IFormatProvider formatter = new NumberFormatInfo { NumberDecimalSeparator = "." };
                    dAnalog = double.Parse(sReceivedAnalog, formatter);

                    dAnalog = dAnalog * 1000;
                    iAnalog = Convert.ToInt32(dAnalog);
                    sAnalog = Convert.ToString(iAnalog);

                    LabelAnalog.Text = sAnalog + " mV";
                }
                else
                {
                    sAnalog = "No signal";

                    LabelAnalog.Text = sAnalog;
                }

                for (int i = 599; i > 0; i--)
                {
                    arrAnalog[0, i] = arrAnalog[0, i - 1];
                    arrAnalog[1, i] = arrAnalog[1, i - 1];
                }

                arrAnalog[0, 0] = sDateTime;
                arrAnalog[1, 0] = sAnalog;

                WriteGridAnalog();

                WriteFrameAnalog();

                if (sHour != sHour2)
                {
                    sHour2 = sHour;
                    sFileName = sYear + "-" + sMonth + "-" + sDay + " " + sHour + sMinute + sSecond;
                }

                WriteFile();

                inAnalog++;

                if (inAnalog >= 599) { inAnalog = 599; }
            }

            if (TrackFrame.Value != iTrackFrame)
            {
                iTrackFrame = TrackFrame.Value;
                groupBox3.Text = "Frame " + Convert.ToString(arrTrackFrame[TrackFrame.Value]);

                if (bButtonConnect == false && inAnalog > 0)
                {
                    WriteFrameAnalog();
                }
            }
        }

        private void WriteGridAnalog()
        {
            GridAnalog.Rows.Clear();

            for (int i = 0; i <= inAnalog; i++)
            {
                GridAnalog.Rows.Add(arrAnalog[0, i], arrAnalog[1, i]);
           }
        }

        private void WriteFrameAnalog()
        {
            FrameAnalog.Series[0].Points.Clear();

            if (inAnalog <= arrTrackFrame[TrackFrame.Value] - 1)
            {
                for (int i = inAnalog; i >= 0; i--)
                {
                    if (arrAnalog[1, i] == "No signal")
                    {
                        FrameAnalog.Series[0].Points.AddXY(arrAnalog[0, i], "-40");
                    }
                    else
                    {
                        FrameAnalog.Series[0].Points.AddXY(arrAnalog[0, i], arrAnalog[1, i]);
                    }
                }
            }
            else
            {
                for (int i = arrTrackFrame[TrackFrame.Value] - 1; i >= 0; i--)
                {
                    if (arrAnalog[1, i] == "No signal")
                    {
                        FrameAnalog.Series[0].Points.AddXY(arrAnalog[0, i], "-40");
                    }
                    else
                    {
                        FrameAnalog.Series[0].Points.AddXY(arrAnalog[0, i], arrAnalog[1, i]);
                    }
                }
            }
        }


        string sFileName;
        private void WriteFile()
        {
            string filename = "Files/Report " + sFileName + ".txt";
            StreamWriter writer = new StreamWriter(filename, true);
            writer.WriteLine(sDateTime + ";" + sAnalog);
            writer.Close();
        }

        private void Form_FormClosing(object sender, FormClosingEventArgs e)
        {
            serialPort.Close();

            SaveSet();

            string configFile = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), CONFIG_NAME);
            if (File.Exists(configFile))
                SaveMainConfAsXml(configFile, Encoding.Unicode);
        }
    }
}
